package game.breeze.astar;

import game.breeze.Disposable;

import java.util.HashSet;
import java.util.Set;

public class AStarNode implements Disposable {

	private int row;
	private int col;
	private boolean start;
	private boolean end;

	// private double localCost; // cost of getting from this square to goal
	private double parentCost; // cost of getting from parent square to this
	// node
	// private double passThroughCost;// cost of
	// getting from the start to the goal
	// through this square

	private AStar maze;

	private Set<AStarNode> adjacencies = new HashSet<AStarNode>();

	private AStarNode parent;

	public void dispose() {
		maze = null;
		adjacencies.clear();
		adjacencies = null;
		parent = null;
	}

	public void reset() {
		start = false;
		end = false;
		parent = null;
	}

	public AStarNode(int row, int col, AStar maze) {

		this.row = row;
		this.col = col;
		this.maze = maze;
	}

	/**
	 * @return the row
	 */
	public int getRow() {
		return row;
	}

	/**
	 * @param row
	 *            the row to set
	 */
	public void setRow(int row) {
		this.row = row;
	}

	/**
	 * @return the col
	 */
	public int getCol() {
		return col;
	}

	/**
	 * @param col
	 *            the col to set
	 */
	public void setCol(int col) {
		this.col = col;
	}

	public boolean isStart() {

		return start;
	}

	public void setStart(boolean start) {

		this.start = start;
	}

	public boolean isEnd() {

		return end;
	}

	public void setEnd(boolean end) {

		this.end = end;
	}

	public Set<AStarNode> getAdjacencies() {

		return adjacencies;
	}

	public void setAdjacencies(Set<AStarNode> adjacencies) {

		this.adjacencies = adjacencies;
	}

	public AStarNode getParent() {

		return parent;
	}

	public void setParent(AStarNode parent) {

		this.parent = parent;
	}

	public void calculateAdjacencies() {

		// int top = row - 1;
		int bottom = row + 1;
		// int left = col - 1;
		int right = col + 1;

		if (bottom < maze.getRows()) {
			if (isAdjacent()) {
				maze.getSquare(bottom, col).addAdjacency(this);
				this.addAdjacency(maze.getSquare(bottom, col));
			}
		}

		if (right < maze.getColumns()) {
			if (isAdjacent()) {
				maze.getSquare(row, right).addAdjacency(this);
				this.addAdjacency(maze.getSquare(row, right));
			}
		}
	}

	public void addAdjacency(AStarNode square) {

		adjacencies.add(square);
	}

	public void removeAdjacency(AStarNode square) {
		adjacencies.remove(square);
	}

	public double getPassThrough(AStarNode goal) {

		if (isStart()) {
			return 0.0;
		}

		return getLocalCost(goal);// + getParentCost();
	}

	public double getLocalCost(AStarNode goal) {

		if (isStart()) {
			return 0.0;
		}

		// localCost = 1.0 * (Math.abs(row - goal.getRow()) + Math.abs(col -
		// goal.getCol()));
		// return localCost;
		return 1.0 * (Math.abs(row - goal.getRow()) + Math.abs(col - goal.getCol()));
	}

	public double getParentCost() {

		if (isStart()) {
			return 0.0;
		}
		// double parentCost;
		if (parentCost == 0.0) {
			parentCost = 1.0 + .5 * (parent.getParentCost() - 1.0);
		}

		return parentCost;
	}

	public boolean isAdjacent() {

		return maze.getGrid()[row][col] == 1;// true;
		// if (Math.random() > .5) {
		// return true;
		// }
		// return false;
	}

}
